package co.edu.usbcali.unidad.presentation.backEndBeans;

import co.edu.usbcali.unidad.exceptions.*;
import co.edu.usbcali.unidad.modelo.*;
import co.edu.usbcali.unidad.modelo.dto.ConceptoDTO;
import co.edu.usbcali.unidad.presentation.businessDelegate.BusinessDelegatorView;
import co.edu.usbcali.unidad.utilities.*;

import com.icesoft.faces.async.render.RenderManager;
import com.icesoft.faces.async.render.Renderable;
import com.icesoft.faces.component.ext.HtmlCommandButton;
import com.icesoft.faces.component.ext.HtmlInputText;
import com.icesoft.faces.component.ext.HtmlSelectOneMenu;
import com.icesoft.faces.component.selectinputdate.SelectInputDate;
import com.icesoft.faces.context.DisposableBean;
import com.icesoft.faces.webapp.xmlhttp.FatalRenderingException;
import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
import com.icesoft.faces.webapp.xmlhttp.RenderingException;
import com.icesoft.faces.webapp.xmlhttp.TransientRenderingException;

import java.math.BigDecimal;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import java.util.Vector;

import javax.faces.event.ValueChangeEvent;
import javax.faces.model.DataModel;
import javax.faces.model.SelectItem;


public class ConceptoView extends DataSource implements Renderable,
DisposableBean {
	private HtmlInputText txtConPorcentajeImpre;
	private HtmlInputText txtConValor;
	private HtmlSelectOneMenu cmbPresupuesto;
	private HtmlSelectOneMenu cmbTipoCategoria;
	private HtmlSelectOneMenu cmbTipoConcepto;
	private HtmlInputText txtConCodigo;
	private HtmlCommandButton btnSave;
	private HtmlCommandButton btnModify;
	private HtmlCommandButton btnDelete;
	private HtmlCommandButton btnClear;
	private boolean renderDataTable;
	private boolean flag = true;
	private RenderManager renderManager;
	private PersistentFacesState state = PersistentFacesState.getInstance();
	private List<Concepto> concepto;
	private List<ConceptoDTO> conceptoDTO;
	private List<SelectItem> listPresupuesto = new ArrayList<SelectItem>();
	private List<SelectItem> listTipoCategoria = new ArrayList<SelectItem>();
	private List<SelectItem> listTipoConcepto = new ArrayList<SelectItem>();

	public ConceptoView() {
		super("");
	}



	public HtmlSelectOneMenu getCmbPresupuesto() {
		try{
			List<Presupuesto> list = BusinessDelegatorView.findByCriteriaInPresupuesto(
					null, null, null);
			listPresupuesto.clear();
			listPresupuesto.add(new SelectItem(0, " --Seleccione Presupuesto-- "));

			for (Presupuesto presupuesto : list) {
				listPresupuesto.add(new SelectItem(presupuesto.getPreCodigo()));
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return cmbPresupuesto;
	}



	public void setCmbPresupuesto(HtmlSelectOneMenu cmbPresupuesto) {
		this.cmbPresupuesto = cmbPresupuesto;
	}



	public HtmlSelectOneMenu getCmbTipoCategoria() {
		try{
			List<TipoCategoria> list = BusinessDelegatorView.findByCriteriaInTipoCategoria(
					null, null, null);
			listTipoCategoria.clear();
			listTipoCategoria.add(new SelectItem(0, " --Seleccione Tipo Categoria-- "));

			for (TipoCategoria tipoCategoria : list) {
				listTipoCategoria.add(new SelectItem(tipoCategoria.getTcaCodigo(), tipoCategoria.getTcaNombre()));
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return cmbTipoCategoria;
	}



	public void setCmbTipoCategoria(HtmlSelectOneMenu cmbTipoCategoria) {
		this.cmbTipoCategoria = cmbTipoCategoria;
	}



	public HtmlSelectOneMenu getCmbTipoConcepto() {
		try{
			List<TipoConcepto> list = BusinessDelegatorView.findByCriteriaInTipoConcepto(
					null, null, null);
			listTipoConcepto.clear();
			listTipoConcepto.add(new SelectItem(0, " --Seleccione Tipo Concepto-- "));

			for (TipoConcepto tipoConcepto : list) {
				listTipoConcepto.add(new SelectItem(tipoConcepto.getTcoCodigo(), tipoConcepto.getTcoNombre()));
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return cmbTipoConcepto;
	}



	public void setCmbTipoConcepto(HtmlSelectOneMenu cmbTipoConcepto) {
		this.cmbTipoConcepto = cmbTipoConcepto;
	}



	public List<SelectItem> getListPresupuesto() {
		return listPresupuesto;
	}



	public void setListPresupuesto(List<SelectItem> listPresupuesto) {
		this.listPresupuesto = listPresupuesto;
	}



	public List<SelectItem> getListTipoCategoria() {
		return listTipoCategoria;
	}



	public void setListTipoCategoria(List<SelectItem> listTipoCategoria) {
		this.listTipoCategoria = listTipoCategoria;
	}



	public List<SelectItem> getListTipoConcepto() {
		return listTipoConcepto;
	}



	public void setListTipoConcepto(List<SelectItem> listTipoConcepto) {
		this.listTipoConcepto = listTipoConcepto;
	}



	public String action_clear() {
		txtConPorcentajeImpre.setValue(null);
		txtConPorcentajeImpre.setDisabled(true);
		txtConValor.setValue(null);
		txtConValor.setDisabled(true);
		cmbPresupuesto.setValue(null);
		cmbPresupuesto.setDisabled(true);
		cmbTipoCategoria.setValue(null);
		cmbTipoCategoria.setDisabled(true);
		cmbTipoConcepto.setValue(null);
		cmbTipoConcepto.setDisabled(true);
		txtConCodigo.setValue(null);
		txtConCodigo.setDisabled(false);
		btnSave.setDisabled(true);
		btnDelete.setDisabled(true);
		btnModify.setDisabled(true);
		btnClear.setDisabled(false);

		return "";
	}

	public void listener_txtId(ValueChangeEvent event) {
		if ((event.getNewValue() != null) && !event.getNewValue().equals("")) {
			Concepto entity = null;

			try {
				String conCodigo = new String(txtConCodigo.getValue()
						.toString());
				entity = BusinessDelegatorView.getConcepto(conCodigo);
			} catch (Exception e) {
				// TODO: handle exception
			}

			if (entity == null) {
				txtConPorcentajeImpre.setDisabled(false);
				txtConValor.setDisabled(false);
				cmbPresupuesto.setDisabled(false);
				cmbTipoCategoria.setDisabled(false);
				cmbTipoConcepto.setDisabled(false);
				txtConCodigo.setDisabled(false);
				btnSave.setDisabled(false);
				btnDelete.setDisabled(true);
				btnModify.setDisabled(true);
				btnClear.setDisabled(false);
			} else {
				txtConPorcentajeImpre.setValue(entity.getConPorcentajeImpre());
				txtConPorcentajeImpre.setDisabled(false);
				txtConValor.setValue(entity.getConValor());
				txtConValor.setDisabled(false);
				cmbPresupuesto.setValue(entity.getPresupuesto()
						.getPreCodigo());
				cmbPresupuesto.setDisabled(false);
				cmbTipoCategoria.setValue(entity.getTipoCategoria()
						.getTcaCodigo());
				cmbTipoCategoria.setDisabled(false);
				cmbTipoConcepto.setValue(entity.getTipoConcepto()
						.getTcoCodigo());
				cmbTipoConcepto.setDisabled(false);
				txtConCodigo.setValue(entity.getConCodigo());
				txtConCodigo.setDisabled(true);
				btnSave.setDisabled(true);
				btnDelete.setDisabled(false);
				btnModify.setDisabled(false);
				btnClear.setDisabled(false);
			}
		}
	}

	public String action_save() {
		try {
			String codigo = txtConCodigo.getValue().toString();
			String porsentaje = txtConPorcentajeImpre.getValue().toString();
			String valor = txtConValor.getValue().toString();
			String preCodigo = cmbPresupuesto.getValue().toString();
			String tcaCodigo = cmbTipoCategoria.getValue().toString();
			String tcoCodigo = cmbTipoConcepto.getValue().toString();

			if (!Utilities.soloNumerosyLetras(codigo)) {
				throw new Exception(
				"El codigo no debe contener caracteres especiales");
			}

			BusinessDelegatorView.saveConcepto(FacesUtils
					.checkString(txtConCodigo), FacesUtils
					.checkLong(txtConPorcentajeImpre), FacesUtils
					.checkFloat(txtConValor), FacesUtils
					.checkString(cmbPresupuesto), FacesUtils
					.checkString(cmbTipoCategoria), FacesUtils
					.checkString(cmbTipoConcepto));
			
			//BusinessDelegatorView.updatePresupuesto(cmbPresupuesto, txtConValor, null, null, null);
			
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYSAVED);
			action_clear();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		return "";
	}

	public String action_delete() {
		try {
			BusinessDelegatorView.deleteConcepto(FacesUtils
					.checkString(txtConCodigo));
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYDELETED);
			action_clear();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		return "";
	}

	public String action_modify() {
		try {
			BusinessDelegatorView.updateConcepto(FacesUtils
					.checkString(txtConCodigo), FacesUtils
					.checkLong(txtConPorcentajeImpre), FacesUtils
					.checkFloat(txtConValor), FacesUtils
					.checkString(cmbPresupuesto), FacesUtils
					.checkString(cmbTipoCategoria), FacesUtils
					.checkString(cmbTipoConcepto));
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYMODIFIED);
			action_clear();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		return "";
	}

	public String action_modifyWitDTO(String conCodigo,
			Long conPorcentajeImpre, Float conValor,
			String preCodigo_Presupuesto, String tcaCodigo_TipoCategoria,
			String tcoCodigo_TipoConcepto) throws Exception {
		try {
			BusinessDelegatorView.updateConcepto(conCodigo, conPorcentajeImpre,
					conValor, preCodigo_Presupuesto, tcaCodigo_TipoCategoria,
					tcoCodigo_TipoConcepto);
			renderManager.getOnDemandRenderer("ConceptoView").requestRender();
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYMODIFIED);
		} catch (Exception e) {
			// renderManager.getOnDemandRenderer("ConceptoView").requestRender();
			FacesUtils.addErrorMessage(e.getMessage());
			throw e;
		}

		return "";
	}

	public List<Concepto> getConcepto() {
		if (flag) {
			try {
				concepto = BusinessDelegatorView.getConcepto();
				flag = false;
			} catch (Exception e) {
				flag = true;
				FacesUtils.addErrorMessage(e.getMessage());
			}
		}

		return concepto;
	}

	public boolean isFlag() {
		return flag;
	}

	public void setConcepto(List<Concepto> concepto) {
		this.concepto = concepto;
	}

	public boolean isRenderDataTable() {
		try {
			if (flag) {
				if (BusinessDelegatorView.findTotalNumberConcepto() > 0) {
					renderDataTable = true;
				} else {
					renderDataTable = false;
				}
			}

			flag = false;
		} catch (Exception e) {
			renderDataTable = false;
			e.printStackTrace();
		}

		return renderDataTable;
	}

	public DataModel getData() {
		state = PersistentFacesState.getInstance();

		if (onePageDataModel == null) {
			onePageDataModel = new LocalDataModel(pageSize);
		}

		return onePageDataModel;
	}

	/**
	 * This is where the Object data is retrieved from the database and returned
	 * as a list of objects for display in the UI.
	 */
	private DataPage<Concepto> getDataPage(int startRow, int pageSize) {
		// Retrieve the total number of objects from the database. This
		// number is required by the DataPage object so the paginator will know
		// the relative location of the page data.
		int totalNumberConcepto = 0;

		try {
			totalNumberConcepto = BusinessDelegatorView
			.findTotalNumberConcepto().intValue();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		// Calculate indices to be displayed in the ui.
		int endIndex = startRow + pageSize;

		if (endIndex > totalNumberConcepto) {
			endIndex = totalNumberConcepto;
		}

		try {
			concepto = BusinessDelegatorView.findPageConcepto(sortColumnName,
					sortAscending, startRow, endIndex - startRow);

			// Remove this Renderable from the existing render groups.
			// leaveRenderGroups();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		// Add this Renderable to the new render groups.
		// joinRenderGroups();
		// Reset the dirtyData flag.
		onePageDataModel.setDirtyData(false);
		// This is required when using Hibernate. If the SessionManager is not
		// cleared or closed objects are cached and stale objects will show up
		// in the table.
		// This way, the detached objects are reread from the database.
		// This call is not required with Hibernate, which uses a Query Hint
		// to clear the l2 cache in the DAO.
		flag = true;

		return new DataPage<Concepto>(totalNumberConcepto, startRow, concepto);
	}

	public DataModel getDataDTO() {
		state = PersistentFacesState.getInstance();

		if (onePageDataModel == null) {
			onePageDataModel = new LocalDataModelDTO(pageSize);
		}

		return onePageDataModel;
	}

	/**
	 * This is where the Object data is retrieved from the database and returned
	 * as a list of objects for display in the UI.
	 */
	private DataPage<ConceptoDTO> getDataPageDTO(int startRow, int pageSize) {
		// Retrieve the total number of objects from the database. This
		// number is required by the DataPage object so the paginator will know
		// the relative location of the page data.
		int totalNumberConcepto = 0;

		try {
			totalNumberConcepto = BusinessDelegatorView
			.findTotalNumberConcepto().intValue();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		// Calculate indices to be displayed in the ui.
		int endIndex = startRow + pageSize;

		if (endIndex > totalNumberConcepto) {
			endIndex = totalNumberConcepto;
		}

		try {
			concepto = BusinessDelegatorView.findPageConcepto(sortColumnName,
					sortAscending, startRow, endIndex - startRow);

			if (Utilities.validationsList(concepto)) {
				conceptoDTO = new ArrayList<ConceptoDTO>();

				for (Concepto conceptoTmp : concepto) {
					ConceptoDTO conceptoDTO2 = new ConceptoDTO();
					conceptoDTO2.setConCodigo(conceptoTmp.getConCodigo()
							.toString());
					conceptoDTO2.setConPorcentajeImpre((conceptoTmp
							.getConPorcentajeImpre() != null) ? conceptoTmp
									.getConPorcentajeImpre().toString() : null);
					conceptoDTO2
					.setConValor((conceptoTmp.getConValor() != null) ? conceptoTmp
							.getConValor().toString()
							: null);
					conceptoDTO2
					.setPreCodigo_Presupuesto((conceptoTmp
							.getPresupuesto().getPreCodigo() != null) ? conceptoTmp
									.getPresupuesto().getPreCodigo().toString()
									: null);
					conceptoDTO2
					.setTcaCodigo_TipoCategoria((conceptoTmp
							.getTipoCategoria().getTcaCodigo() != null) ? conceptoTmp
									.getTipoCategoria().getTcaCodigo()
									.toString()
									: null);
					conceptoDTO2
					.setTcoCodigo_TipoConcepto((conceptoTmp
							.getTipoConcepto().getTcoCodigo() != null) ? conceptoTmp
									.getTipoConcepto().getTcoCodigo()
									.toString()
									: null);
					conceptoDTO2.setConcepto(conceptoTmp);
					conceptoDTO2.setConceptoView(this);
					conceptoDTO.add(conceptoDTO2);
				}
			}

			// Remove this Renderable from the existing render groups.
			leaveRenderGroups();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		// Add this Renderable to the new render groups.
		joinRenderGroups();
		// Reset the dirtyData flag.
		onePageDataModel.setDirtyData(false);
		// This is required when using Hibernate. If the SessionManager is not
		// cleared or closed objects are cached and stale objects will show up
		// in the table.
		// This way, the detached objects are reread from the database.
		// This call is not required with Hibernate, which uses a Query Hint
		// to clear the l2 cache in the DAO.
		flag = true;

		return new DataPage<ConceptoDTO>(totalNumberConcepto, startRow,
				conceptoDTO);
	}

	protected boolean isDefaultAscending(String sortColumn) {
		return true;
	}

	/**
	 * This method is called when a render call is made from the server. Render
	 * calls are only made to views containing an updated record. The data is
	 * marked as dirty to trigger a fetch of the updated record from the
	 * database before rendering takes place.
	 */
	public PersistentFacesState getState() {
		onePageDataModel.setDirtyData();

		return state;
	}

	/**
	 * This method is called from faces-config.xml with each new session.
	 */
	public void setRenderManager(RenderManager renderManager) {
		this.renderManager = renderManager;
	}

	public void renderingException(RenderingException arg0) {
		if (arg0 instanceof TransientRenderingException) {
		} else if (arg0 instanceof FatalRenderingException) {
			// Remove from existing Customer render groups.
			leaveRenderGroups();
		}
	}

	/**
	 * Remove this Renderable from existing uiCustomerBeans render groups.
	 * OnDemandRenderers are named/created using the underlying Customer Number.
	 */
	private void leaveRenderGroups() {
		if (Utilities.validationsList(conceptoDTO)) {
			for (ConceptoDTO conceptoTmp : conceptoDTO) {
				renderManager.getOnDemandRenderer("ConceptoView").remove(this);
			}
		}
	}

	/**
	 * Add this Renderable to the new uiCustomerBeans render groups.
	 * OnDemandRenderers are named/created using the underlying Customer Number.
	 */
	private void joinRenderGroups() {
		if (Utilities.validationsList(conceptoDTO)) {
			for (ConceptoDTO conceptoTmp : conceptoDTO) {
				renderManager.getOnDemandRenderer("ConceptoView").add(this);
			}
		}
	}

	public void dispose() throws Exception {
	}

	public RenderManager getRenderManager() {
		return renderManager;
	}

	public void setState(PersistentFacesState state) {
		this.state = state;
	}

	public HtmlInputText getTxtConPorcentajeImpre() {
		return txtConPorcentajeImpre;
	}

	public void setTxtConPorcentajeImpre(HtmlInputText txtConPorcentajeImpre) {
		this.txtConPorcentajeImpre = txtConPorcentajeImpre;
	}

	public HtmlInputText getTxtConValor() {
		return txtConValor;
	}

	public void setTxtConValor(HtmlInputText txtConValor) {
		this.txtConValor = txtConValor;
	}

	public HtmlInputText getTxtConCodigo() {
		return txtConCodigo;
	}

	public void setTxtConCodigo(HtmlInputText txtConCodigo) {
		this.txtConCodigo = txtConCodigo;
	}

	public HtmlCommandButton getBtnSave() {
		return btnSave;
	}

	public void setBtnSave(HtmlCommandButton btnSave) {
		this.btnSave = btnSave;
	}

	public HtmlCommandButton getBtnModify() {
		return btnModify;
	}

	public void setBtnModify(HtmlCommandButton btnModify) {
		this.btnModify = btnModify;
	}

	public HtmlCommandButton getBtnDelete() {
		return btnDelete;
	}

	public void setBtnDelete(HtmlCommandButton btnDelete) {
		this.btnDelete = btnDelete;
	}

	public HtmlCommandButton getBtnClear() {
		return btnClear;
	}

	public void setBtnClear(HtmlCommandButton btnClear) {
		this.btnClear = btnClear;
	}

	public void setRenderDataTable(boolean renderDataTable) {
		this.renderDataTable = renderDataTable;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	public List<ConceptoDTO> getConceptoDTO() {
		return conceptoDTO;
	}

	public void setConceptoDTO(List<ConceptoDTO> conceptoDTO) {
		this.conceptoDTO = conceptoDTO;
	}

	public TimeZone getTimeZone() {
		return java.util.TimeZone.getDefault();
	}

	/**
	 * A special type of JSF DataModel to allow a datatable and datapaginator to
	 * page through a large set of data without having to hold the entire set of
	 * data in memory at once. Any time a managed bean wants to avoid holding an
	 * entire dataset, the managed bean declares this inner class which extends
	 * PagedListDataModel and implements the fetchData method. fetchData is
	 * called as needed when the table requires data that isn't available in the
	 * current data page held by this object. This requires the managed bean
	 * (and in general the business method that the managed bean uses) to
	 * provide the data wrapped in a DataPage object that provides info on the
	 * full size of the dataset.
	 */
	private class LocalDataModel extends PagedListDataModel {
		public LocalDataModel(int pageSize) {
			super(pageSize);
		}

		public DataPage<Concepto> fetchPage(int startRow, int pageSize) {
			// call enclosing managed bean method to fetch the data
			return getDataPage(startRow, pageSize);
		}
	}

	private class LocalDataModelDTO extends PagedListDataModel {
		public LocalDataModelDTO(int pageSize) {
			super(pageSize);
		}

		public DataPage<ConceptoDTO> fetchPage(int startRow, int pageSize) {
			// call enclosing managed bean method to fetch the data
			return getDataPageDTO(startRow, pageSize);
		}
	}
}
